package acadclockmidletpkg;

import java.util.Calendar;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;

/**
 * Класс определяющий вывод информации о текущих вреемни, дате, дне недели,
 * номере недели в семестре и её типе (числитель/знаменатель, первый/второй).
 *
 * @author Kolomoets G.P.
 * @version 1.0
 */
public class MainScreen extends Canvas {

    private Calendar calendar;
    private static String weekDays[] = {"Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота"};
    RMSWorker worker;

    /**
     * Конструктор - создание объекта Calendar с текущей датой и времением и
     * инициализации объекта, работающего с БД.
     */
    public MainScreen() {
        super();
        this.calendar = Calendar.getInstance();
        worker = MainMIDlet.getWorker();
        /*Инициализация хранилища записей*/
        worker.initializeRecordStore();
    }

    /**
     * Отрисовка главного экрана.
     *
     * @param g холст экрана
     */
    protected void paint(Graphics g) {
        int width = getWidth();
        int height = getHeight();
        g.setColor(10, 80, 200);
        Font myFont = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_LARGE);
        g.setFont(myFont);
        printCurrentTime(g, width, height);
        printCurrentDate(g, width, height);
        printCurrentWeekDay(g, width, height);
        printCurrentWeekNumberAndType(g, width, height);
        printTimeUntilNextPair(g, width, height);
    }

    /**
     * Вывод текущих часов и минут.
     *
     * @param calendar календарь
     * @param g холст экрана
     * @param width ширина экрана
     * @param height высота экрана
     */
    private void printCurrentTime(Graphics g, int width, int height) {
        /*Вывод текущих часов и минут*/
        String hours = String.valueOf(getCalendar().get(Calendar.HOUR_OF_DAY));
        String minutes = String.valueOf(getCalendar().get(Calendar.MINUTE));
        String time = addZeroToField(hours) + ":" + addZeroToField(minutes);
        g.drawString(time, width / 2, height / 2 - 60, Graphics.TOP | Graphics.HCENTER);
    }

    /**
     * Вывод текущих дня, месяца и года.
     *
     * @param calendar календарь
     * @param g холст экрана
     * @param width ширина экрана
     * @param height высота экрана
     */
    private void printCurrentDate(Graphics g, int width, int height) {
        String day = String.valueOf(getCalendar().get(Calendar.DAY_OF_MONTH));
        String month = String.valueOf(getCalendar().get(Calendar.MONTH) + 1);
        String year = String.valueOf(getCalendar().get(Calendar.YEAR));
        String curDate = addZeroToField(day) + "." + addZeroToField(month) + "." + year;
        g.drawString(curDate, width / 2, height / 2 - 40, Graphics.TOP | Graphics.HCENTER);
    }

    /**
     * Вывод названия текущего дня недели.
     *
     * @param calendar календарь
     * @param g холст экрана
     * @param width ширина экрана
     * @param height высота экрана
     */
    private void printCurrentWeekDay(Graphics g, int width, int height) {
        int weekDay = getCalendar().get(Calendar.DAY_OF_WEEK) - 1;
        g.drawString(weekDays[weekDay], width / 2, height / 2 - 20, Graphics.TOP | Graphics.HCENTER);
    }

    /**
     * Вывод номера недели от начала семестра и её типа: числитель/знаменатель,
     * первый/второй.При этом отслеживаются недели аудиторных занятий (16),
     * недели сессий (+3). При ихпревышении выводится сообщение-напоминание о
     * перенастройке дат начала семестров.
     *
     * @param calendar календарь
     * @param g холст экрана
     * @param width ширина экрана
     * @param height высота экрана
     */
    private void printCurrentWeekNumberAndType(Graphics g, int width, int height) {
        //Номер недели, начиная с начала учебного года
        int yearWeekNumber;
        //Номер недели, начиная с начала семестра
        int semesterWeekNumber;
        String weekType;
        String weekTypeNumber;
        long currentDate = getCalendar().getTime().getTime();
        long firstSemesterBegin = worker.readDateRecord(1).getTime();
        long secondSemesterBegin = worker.readDateRecord(2).getTime();
        yearWeekNumber = (int) ((currentDate - firstSemesterBegin) / 1000 / 60 / 60 / 24 / 7 + 1);
        if (currentDate >= firstSemesterBegin && currentDate < secondSemesterBegin) {
            semesterWeekNumber = yearWeekNumber;
            if (yearWeekNumber % 2 == 0) {
                weekType = "знаменатель";
                if (yearWeekNumber % 4 == 0) {
                    weekTypeNumber = " 2-й ";
                } else {
                    weekTypeNumber = " 1-й ";
                }
            } else {
                weekType = "числитель";
                if ((yearWeekNumber - 1) % 4 == 0) {
                    weekTypeNumber = " 1-й ";
                } else {
                    weekTypeNumber = " 2-й ";
                }
            }
        } else {
            semesterWeekNumber = (int) ((currentDate - secondSemesterBegin) / 1000 / 60 / 60 / 24 / 7 + 1);
            if (yearWeekNumber % 2 == 0) {
                weekType = "знаменатель";
                if (yearWeekNumber % 4 == 0) {
                    weekTypeNumber = " 2-й ";
                } else {
                    weekTypeNumber = " 1-й ";
                }
            } else {
                weekType = "числитель";
                if ((yearWeekNumber - 1) % 4 == 0) {
                    weekTypeNumber = " 1-й ";
                } else {
                    weekTypeNumber = " 2-й ";
                }
            }
        }
        if (semesterWeekNumber <= 16) {
            g.drawString(String.valueOf(semesterWeekNumber) + " неделя,", width / 2, height / 2, Graphics.TOP | Graphics.HCENTER);
            g.drawString(weekTypeNumber + weekType, width / 2, height / 2 + 20, Graphics.TOP | Graphics.HCENTER);
        } else if (semesterWeekNumber < 20) {
            g.drawString("Нет занятий", width / 2, height / 2, Graphics.TOP | Graphics.HCENTER);
        } else {
            g.drawString("Установите даты", width / 2, height / 2, Graphics.TOP | Graphics.HCENTER);
            g.drawString("начала семестров", width / 2, height / 2 + 20, Graphics.TOP | Graphics.HCENTER);
        }
    }

    /**
     * Вывод количества минут до следующей пары.
     *
     * @param g холст экрана
     * @param width ширина экрана
     * @param height высота экрана
     * @throws NumberFormatException при считывании неициализированного поля
     * pairDuration
     */
    private void printTimeUntilNextPair(Graphics g, int width, int height) throws NumberFormatException {
        String timeUntilNextPair;
        long MINUTES_IN_TIME = 60 * 1000;
        /*Количество милисекунд в одних сутках*/
        long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
        /*Расчёт текщего времни внутри текущих суток*/
        long currentTime = (getCalendar().getTime().getTime() % MILLIS_PER_DAY);
        /*Поскольку при считывании неициализированного поля pairDuration
         (форма настроека ещё не создаётся) метод parseLong выбрасывет 
         для пустой строки "" исключение, обрабатываем его, устанавливая
         значение по умолчанию*/
        long pairDuration;
        /*Ещё одна "перестраховка" от парсинга пустой строки*/
        try {
            pairDuration = Long.parseLong(worker.readTextRecord(3));
        } catch (NumberFormatException ex) {
            pairDuration = Long.parseLong("75");
        }
        long firstPairBegin = worker.readDateRecord(4).getTime();
        long secondPairBegin = worker.readDateRecord(5).getTime();
        long thirdPairBegin = worker.readDateRecord(6).getTime();
        long fourthPairBegin = worker.readDateRecord(7).getTime();
        long fifthPairBegin = worker.readDateRecord(8).getTime();
        long sixthPairBegin = worker.readDateRecord(9).getTime();
        long seventhPairBegin = worker.readDateRecord(10).getTime();
        long eighthPairBegin = worker.readDateRecord(11).getTime();
        long ninethPairBegin = worker.readDateRecord(12).getTime();
        if (currentTime >= firstPairBegin && currentTime < secondPairBegin) {
            timeUntilNextPair = "до 2-й пары " + (int) ((secondPairBegin - currentTime) / MINUTES_IN_TIME) + " мин";
        } else if (currentTime >= secondPairBegin && currentTime < thirdPairBegin) {
            timeUntilNextPair = "до 3-й пары " + (int) ((thirdPairBegin - currentTime) / MINUTES_IN_TIME) + " мин";
        } else if (currentTime >= thirdPairBegin && currentTime < fourthPairBegin) {
            timeUntilNextPair = "до 4-й пары " + (int) ((fourthPairBegin - currentTime) / MINUTES_IN_TIME) + " мин";
        } else if (currentTime >= fourthPairBegin && currentTime < fifthPairBegin) {
            timeUntilNextPair = "до 5-й пары " + (int) ((fifthPairBegin - currentTime) / MINUTES_IN_TIME) + " мин";
        } else if (currentTime >= fifthPairBegin && currentTime < sixthPairBegin) {
            timeUntilNextPair = "до 6-й пары " + (int) ((sixthPairBegin - currentTime) / MINUTES_IN_TIME) + " мин";
        } else if (currentTime >= sixthPairBegin && currentTime < seventhPairBegin) {
            timeUntilNextPair = "до 7-й пары " + (int) ((seventhPairBegin - currentTime) / MINUTES_IN_TIME) + " мин";
        } else if (currentTime >= seventhPairBegin && currentTime < eighthPairBegin) {
            timeUntilNextPair = "до 8-й пары " + (int) ((eighthPairBegin - currentTime) / MINUTES_IN_TIME) + " мин";
        } else if (currentTime >= eighthPairBegin && currentTime < ninethPairBegin) {
            timeUntilNextPair = "до 9-й пары " + (int) ((ninethPairBegin - currentTime) / MINUTES_IN_TIME) + " мин";
        } else if (currentTime >= ninethPairBegin && currentTime < (ninethPairBegin + pairDuration * MINUTES_IN_TIME)) {
            timeUntilNextPair = "сейчас 9 пара";
        } else {
            timeUntilNextPair = "сейчас нет пар";
        }
        g.drawString(timeUntilNextPair, width / 2, height / 2 + 50, Graphics.TOP | Graphics.HCENTER);
    }

    /**
     * Добавление незначащего нуля к показаниям часов, минут, дней и месяцев.
     *
     * @param field текстовое поле, которому добавляется незначащий нуль
     * @return 2-хсимвольную строку
     */
    private String addZeroToField(String field) {
        return field.length() > 1 ? field : "0" + field;
    }

    /**
     * Получение календаря с текщими датой/временем.
     * @return календарь с текущими датой/временем
     */
    public Calendar getCalendar() {
        return calendar;
    }
}
